package cn.itcast.web.shiro;

import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/*
*  自定义的realm域,有两个功能:1.身份认证(登录)  2.权限验证
*     建议继承 AuthorizingRealm
*/
public class AuthRealm extends AuthorizingRealm{

    @Autowired
    UserService userService;

    @Autowired
    ModuleService moduleService;

    @Override
    /*
    * 权限验证的操作
    * */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.获取登陆的用户
        User loginUser = (User) principalCollection.getPrimaryPrincipal();

        //2.获取用户拥有的权限列表
        List<Module> moduleList = moduleService.findModulesByUser(loginUser);

        //3.创建权限验证的信息对象,设置权限列表信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //遍历用户权限list,获取到每个权限,将每个权限的名字获取到之后,放入一个set中,最后将set设置info中
        Set<String> set = new HashSet<>();

        for (Module module : moduleList) {
            set.add(module.getName());
        }

        info.setStringPermissions(set);
        System.out.println(set);
        return info;
    }

    @Override
    /*
    * 身份认证的操作
    * */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.从token令牌中获取用户名
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String email = token.getUsername();

        //2.调用userService.findByEmail(email),返回user对象
        User loginUser = userService.findByEmail(email);

        //3.判断用户是否为空,若为null ,就返回null(底层就会抛异常)
        //4.若不为null,就代表找到用户,封装身份认证的信息对象(将用户,数据库中密码,realm的名字),然后返回
        if (loginUser!=null) {
            /*
                参数1:查询到的用户
                参数2:数据库中的密码
                参数3:realm的名字
             */
            return  new SimpleAuthenticationInfo(loginUser,loginUser.getPassword(),this.getName());
        }
        return null;
    }
}
